package com.cn.wanxi.service.impl;

import com.cn.wanxi.common.ParseTool;
import com.cn.wanxi.common.RedisNumTool;
import com.cn.wanxi.common.ThreadTool;
import com.cn.wanxi.entity.NavEntity;
import com.cn.wanxi.entity.ResultEntity;
import com.cn.wanxi.mapper.NavMapper;
import com.cn.wanxi.service.INavService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;

@Service
public class NavServiceImpl implements INavService {
    @Autowired
    private NavMapper navMapper;

    @Override
    public ResultEntity add(NavEntity navEntity) {
        int result = navMapper.add(navEntity);
        resetCache(result, 0);
        return ResultEntity.success(result);
    }

    @Override
    public ResultEntity update(NavEntity navEntity) {
        int result = navMapper.update(navEntity);
        resetCache(result, navEntity.getId());
        return ResultEntity.success(result);
    }

    @Override
    public ResultEntity delete(NavEntity navEntity) {
        int result = navMapper.delete(navEntity);
        resetCache(result, navEntity.getId());
        return ResultEntity.success(result);
    }

    @Override
    public List<NavEntity> findAll(NavEntity navEntity) {
        final List<NavEntity>[] list = new List[]{new ArrayList<>()};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                list[0] = findAllCache(navEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return list[0];
    }

    @Override
    public ResultEntity<NavEntity> findById(NavEntity navEntity) {
        final NavEntity[] model = {new NavEntity()};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                model[0] = findByIdCache(navEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return ResultEntity.success(model[0]);
    }

    @Override
    public Integer getCount(NavEntity navEntity) {
        final int[] result = {-1};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                result[0] = findCountCache(navEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return result[0];
    }
    /**
     * 查找缓存，并判断是否从缓存取值
     *
     * @param navModel
     * @return
     */
    private synchronized List<NavEntity> findAllCache(NavEntity navModel) {
        List<NavEntity> list = new ArrayList<>();
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_NAV);
        boolean cache = jedis.exists("navModelContent") && judgeModel(navModel);
        if (cache) {
            int length = Math.toIntExact(jedis.llen("navModelContent"));
            for (int i = 0; i < length; i++) {
                NavEntity model = new NavEntity();
                model.setId(ParseTool.StringToInt(jedis.lindex("navModelId", i)));
                model.setSort(ParseTool.StringToInt(jedis.lindex("navModelSort", i)));
                model.setContent(jedis.lindex("navModelContent", i));
                model.setHref(jedis.lindex("navModelHref", i));
                model.setEnable(ParseTool.StringToInt(jedis.lindex("navModelEnable", i)));
                list.add(model);
            }
        } else {
            list = navMapper.findAll(navModel);
            if (judgeModel(navModel)) {
                for (NavEntity model :
                        list) {
                    jedis.rpush("navModelId", String.valueOf(model.getId()));
                    jedis.rpush("navModelSort", String.valueOf(model.getSort()));
                    jedis.rpush("navModelContent", model.getContent());
                    jedis.rpush("navModelHref", model.getHref());
                    jedis.rpush("navModelEnable", String.valueOf(model.getEnable()));
                }
            }
        }
        return list;
    }

    /**
     * 查找单个导航是否存在缓存
     *
     * @param navModel
     * @return
     */
    private synchronized NavEntity findByIdCache(NavEntity navModel) {
        NavEntity model = new NavEntity();
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_NAV);
        String cacheName = "navModel_id_" + navModel.getId();
        boolean cache = jedis.exists(cacheName);
        if (cache) {
            model.setId(ParseTool.StringToInt(jedis.hget(cacheName, "id")));
            model.setSort(ParseTool.StringToInt(jedis.hget(cacheName, "sort")));
            model.setContent(jedis.hget(cacheName, "content"));
            model.setHref(jedis.hget(cacheName, "href"));
            model.setEnable(ParseTool.StringToInt(jedis.hget(cacheName, "enable")));
        } else {
            model = navMapper.findById(navModel);
            jedis.hset(cacheName, "id", String.valueOf(model.getId()));
            jedis.hset(cacheName, "sort", String.valueOf(model.getSort()));
            jedis.hset(cacheName, "content", model.getContent());
            jedis.hset(cacheName, "href", model.getHref());
            jedis.hset(cacheName, "enable", String.valueOf(model.getEnable()));
        }
        return model;
    }

    /**
     * 获取总数缓存
     * @param navModel
     * @return
     */
    private synchronized int findCountCache(NavEntity navModel) {
        int result = -1;
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_NAV);
        boolean cache = jedis.exists("navModelCount") && judgeModel(navModel);
        if (cache) {
            result = ParseTool.StringToInt(jedis.get("navModelCount"));
        } else {
            result = navMapper.getCount(navModel);
            if (judgeModel(navModel)) {
                jedis.set("navModelCount", String.valueOf(result));
            }
        }
        return result;
    }

    /**
     * 更新后删除Redis中的缓存
     *
     * @param result
     */
    private void resetCache(int result, int id) {
        if (result > 0) {
            Jedis jedis = new Jedis();
            jedis.select(RedisNumTool.REDIS_NAV);
            jedis.del("navModelId", "navModelSort", "navModelContent", "navModelHref");
            jedis.del("navModel_id_" + id);
            jedis.del("navModelCount");
        }
    }

    /**
     * 判断model内是否有值
     * 没有值返回true
     *
     * @param model
     * @return
     */
    private boolean judgeModel(NavEntity model) {
        return model.getId() == null &&
                model.getSort() == null &&
                model.getContent() == null &&
                model.getHref() == null &&
                ParseTool.enableToInt(model.getEnable()) == 1 &&
                ParseTool.pageToInt(model.getPage()) == 1 &&
                ParseTool.limitToInt(model.getLimit()) == 10;
    }
}
